package master

import (
	"encoding/json"
	"net"
	"net/http"
	"strconv"
	"time"

	"gitee.com/taotao_today/crontab/crontab/common"
)

type ApiServer struct {
	httpServer *http.Server
}

var G_ApiServer *ApiServer

// 将任务保存到 ETCD 中   POST job={"name":"job1","command":"echo hello","cronExpr":"*****"}
func handleJobSave(resp http.ResponseWriter, req *http.Request) {
	var job common.Job
	var postJob string
	var bytes []byte
	var err error
	var oldJob *common.Job
	// 1. 解析post表单
	err = req.ParseForm()
	if err != nil {
		goto ERR
	}
	// 2. 取出表单中的数据
	postJob = req.PostForm.Get("job")

	// 3. 反序列化job
	err = json.Unmarshal([]byte(postJob), &job)
	if err != nil {
		goto ERR
	}

	// 4. 保存到etcd
	oldJob, err = G_jobMgr.SaveJob(&job)
	if err != nil {
		goto ERR
	}

	// 5. 返回正常应答 ({"code":0,"msg":"","data":{....}})
	bytes, err = common.BuildResp(0, "success", oldJob)
	if err == nil {
		resp.Write(bytes)
	}
	return
ERR:
	// 6. 异常返回
	bytes, err = common.BuildResp(-1, err.Error(), nil)
	if err == nil {
		resp.Write(bytes)
	}
}

// 删除任务接口  POST /job/delete name=job1
func handleJobDel(resp http.ResponseWriter, req *http.Request) {
	var deleteJob *common.Job
	var name string
	var bytes []byte
	// 1. 解析post表单
	err := req.ParseForm()
	if err != nil {
		goto ERR
	}

	// 2. 获取要删除的任务名
	name = req.PostForm.Get("name")

	// 3.从etcd删除任务
	deleteJob, err = G_jobMgr.DeleteJob(name)
	if err != nil {
		goto ERR
	}

	// 4. 返回正常应答 ({"code":0,"msg":"","data":{....}})
	bytes, err = common.BuildResp(0, "success", deleteJob)
	if err == nil {
		resp.Write(bytes)
	}
	return
ERR:
	// 5. 异常返回
	bytes, err = common.BuildResp(-1, err.Error(), nil)
	if err == nil {
		resp.Write(bytes)
	}
}

// 列举所有crontab任务  fixme: 实现翻页功能
func handleJobList(resp http.ResponseWriter, req *http.Request) {
	var bytes []byte
	jobList, err := G_jobMgr.ListJob()
	if err != nil {
		goto ERR
	}
	// 返回正常应答 ({"code":0,"msg":"","data":{....}})
	bytes, err = common.BuildResp(0, "success", jobList)
	if err == nil {
		resp.Write(bytes)
	}
	return
ERR:
	// 5. 异常返回
	bytes, err = common.BuildResp(-1, err.Error(), nil)
	if err == nil {
		resp.Write(bytes)
	}

}

// 强制杀死某个任务
func handleJobKill(resp http.ResponseWriter, req *http.Request) {
	var name string
	var bytes []byte
	// 1. 解析post表单
	err := req.ParseForm()
	if err != nil {
		goto ERR
	}

	// 2. 获取表单参数
	name = req.PostForm.Get("name")
	err = G_jobMgr.KillJob(name)
	if err != nil {
		goto ERR
	}
	// 4. 返回正常应答 ({"code":0,"msg":"","data":{....}})
	bytes, err = common.BuildResp(0, "success", nil)
	if err == nil {
		resp.Write(bytes)
	}
	return
ERR:
	// 5. 异常返回
	bytes, err = common.BuildResp(-1, err.Error(), nil)
	if err == nil {
		resp.Write(bytes)
	}
}

// 查询任务日志
func handleJobLog(resp http.ResponseWriter, req *http.Request) {
	var (
		err        error
		name       string // 任务名字
		skipParam  string // 从第几条开始
		limitParam string // 返回多少条
		skip       int
		limit      int
		logArr     []*common.JobLog
		bytes      []byte
	)

	// 解析GET参数
	if err = req.ParseForm(); err != nil {
		goto ERR
	}

	// 获取请求参数 /job/log?name=job10&skip=0&limit=10
	name = req.Form.Get("name")
	skipParam = req.Form.Get("skip")
	limitParam = req.Form.Get("limit")
	if skip, err = strconv.Atoi(skipParam); err != nil {
		skip = 0
	}
	if limit, err = strconv.Atoi(limitParam); err != nil {
		limit = 20
	}

	if logArr, err = G_logMgr.ListLog(name, skip, limit); err != nil {
		goto ERR
	}
	// 正常应答
	if bytes, err = common.BuildResp(0, "success", logArr); err == nil {
		resp.Write(bytes)
	}
	return
ERR:
	if bytes, err := common.BuildResp(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
}

// 获取健康worker节点列表
func handleWorkerList(resp http.ResponseWriter, req *http.Request) {
	var (
		workerArr []string
		err       error
		bytes     []byte
	)

	if workerArr, err = G_workerMgr.ListWorkers(); err != nil {
		goto ERR
	}

	// 正常应答
	if bytes, err = common.BuildResp(0, "success", workerArr); err == nil {
		resp.Write(bytes)
	}
	return

ERR:
	if bytes, err = common.BuildResp(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
}

// InitApiServer 初始化APIServer
func InitApiServer() (err error) {

	// 配置路由
	mux := http.NewServeMux()
	mux.HandleFunc("/job/save", handleJobSave)
	mux.HandleFunc("/job/delete", handleJobDel)
	mux.HandleFunc("/job/list", handleJobList)
	mux.HandleFunc("/job/kill", handleJobKill)
	mux.HandleFunc("/job/log", handleJobLog)
	mux.HandleFunc("/worker/list", handleWorkerList)

	// 如果是接口请求就调用上面的接口，如果不是则尝试获取静态资源
	// 静态文件目录
	staticDir := http.Dir(G_config.WebRoot)
	staticHandle := http.FileServer(staticDir)           // staticHandle  ->  /index.html
	mux.Handle("/", http.StripPrefix("/", staticHandle)) // StripPrefix 去掉 / 找crontab/webroot/index.html

	// 启动TCP监听
	listen, err := net.Listen("tcp", ":"+strconv.Itoa(G_config.APIPort))
	if err != nil {
		return
	}

	// 创建httpServer
	httpServer := &http.Server{
		ReadTimeout:  time.Duration(G_config.APIReadTimeout) * time.Millisecond,
		WriteTimeout: time.Duration(G_config.APIWriteTimeout) * time.Millisecond,
		Handler:      mux,
	}

	// 初始化单例对象
	G_ApiServer = &ApiServer{httpServer: httpServer}

	// 启动服务端
	go httpServer.Serve(listen)
	return
}
